package com.whpost.api.controller.wx;

import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.fastjson.JSONObject;
import com.whpost.service.dao.t.THyxxDao;
import com.whpost.service.entity.t.THyxx;
import com.whpost.service.entity.tools.ResultInfo;
import com.whpost.service.tools.Aes;
import com.whpost.service.tools.ToolBean;
import com.whpost.service.wx.entiy.ReqLoginSjh;
import com.whpost.service.wx.entiy.ReqWxLogin;
import com.whpost.service.wx.service.WechatMessageService;
import com.whpost.service.wx.service.WechatServices;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.RandomUtils;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.HttpStatusCodeException;
import org.springframework.web.client.RestTemplate;

import java.io.*;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Map;

@RestController
@RequestMapping("/wx")
public class WechatController {

    @Autowired
    private WxMpService wxMpService;

    @Autowired
    private WechatMessageService messageService;

    @Autowired
    private WechatServices wechatServices;

    @Resource
    private THyxxDao tHyxxDao;

    /**
     * 微信服务器校验接口
     */
    @GetMapping(produces = "text/plain;charset=utf-8")
    public String checkSignature(
            @RequestParam(name = "signature", required = false) String signature,
            @RequestParam(name = "timestamp", required = false) String timestamp,
            @RequestParam(name = "nonce", required = false) String nonce,
            @RequestParam(name = "echostr", required = false) String echostr) {

        if (wxMpService.checkSignature(timestamp, nonce, signature)) {
            return echostr;
        }
        return "非法请求";
    }

    /**
     * 处理微信消息
     */
    @PostMapping(produces = "application/xml;charset=utf-8")
    public String handleMessage(@RequestBody String requestBody,
                                @RequestParam("signature") String signature,
                                @RequestParam("timestamp") String timestamp,
                                @RequestParam("nonce") String nonce,
                                @RequestParam(name = "encrypt_type", required = false) String encryptType,
                                @RequestParam(name = "msg_signature", required = false) String msgSignature) {

        WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(requestBody);
        WxMpXmlOutMessage outMessage = messageService.handleEvent(inMessage);

        return outMessage == null ? "" : outMessage.toXml();
    }

//    /**
//     * 生成永久二维码
//     * @param response
//     * @param sceneStr
//     * @param fileName
//     * @return
//     */
//    @GetMapping("/qrcode/permanent")
//    public ResponseEntity<String> generatePermanentQrCode(
//            HttpServletResponse response,
//            @RequestParam(value = "scene", required = true) String sceneStr,
//            @RequestParam(value = "fileName", required = true) String fileName
//    ) {
//        // 固定存储地址：根据实际环境修改
//        final String QR_CODE_STORAGE_PATH = "/home/wx/qrcodes/";
//
//        try {
//            // 1. 参数校验
//            // 1.1 场景值校验（JDK 17 推荐使用 StandardCharsets.UTF_8）
//            if (sceneStr == null || sceneStr.isEmpty()) {
//                ToolBean.info("生成永久二维码失败：场景值不能为空");
//                return ResponseEntity.badRequest().body("场景值不能为空");
//            }
//            // 使用 StandardCharsets.UTF_8 并添加非空校验，确保兼容性
//            Charset utf8 = StandardCharsets.UTF_8;
//            if (utf8 == null) {
//                utf8 = Charset.forName("UTF-8"); // 双重保障
//            }
//            if (sceneStr.getBytes(utf8).length > 64) {
//                ToolBean.info("生成永久二维码失败：场景值过长（超过64字节），场景值：[" + sceneStr + "]");
//                return ResponseEntity.badRequest().body("场景值不能超过64字节");
//            }
//
//            // 1.2 文件名校验
//            String validFileName = fileName.replaceAll("[\\\\/:*?\"<>|]", "_");
//            if (validFileName.isEmpty()) {
//                ToolBean.info("生成永久二维码失败：文件名无效，原始文件名：[" + fileName + "]");
//                return ResponseEntity.badRequest().body("文件名包含不合法字符");
//            }
//            if (!validFileName.toLowerCase().endsWith(".png")) {
//                validFileName += ".png";
//            }
//
//            // 2. 生成永久二维码
//            WxMpQrCodeTicket ticket = wxMpService.getQrcodeService()
//                    .qrCodeCreateLastTicket(sceneStr);
//
//            if (ticket == null || ticket.getTicket() == null) {
//                ToolBean.info("生成永久二维码失败：ticket为空，场景值：[" + sceneStr + "]");
//                return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
//                        .body("生成二维码失败：系统异常");
//            }
//
//            // 3. 获取二维码图片字节流（JDK 17 支持 is.readAllBytes()）
//            String qrCodeUrl = wxMpService.getQrcodeService().qrCodePictureUrl(ticket.getTicket());
//            ToolBean.info("二维码图片URL：[" + qrCodeUrl + "]，场景值：[" + sceneStr + "]");
//
//            byte[] qrCodeBytes;
//            try (InputStream is = new URL(qrCodeUrl).openStream()) {
//                qrCodeBytes = is.readAllBytes(); // JDK 9+ 支持，JDK 17 完全兼容
//            }
//
//            // 4. 本地存储二维码
//            File storageDir = new File(QR_CODE_STORAGE_PATH);
//            if (!storageDir.exists() && !storageDir.mkdirs()) {
//                throw new RuntimeException("无法创建存储目录：" + QR_CODE_STORAGE_PATH);
//            }
//            String filePath = QR_CODE_STORAGE_PATH + validFileName;
//            Files.write(Paths.get(filePath), qrCodeBytes);
//            ToolBean.info("二维码已保存至本地：[" + filePath + "]，场景值：[" + sceneStr + "]");
//
//            // 5. 输出图片到响应流
//            response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
//            response.setHeader("Pragma", "no-cache");
//            response.setDateHeader("Expires", 0);
//            response.setContentType("image/png");
//            response.setContentLength(qrCodeBytes.length);
//
//            try (OutputStream os = response.getOutputStream()) {
//                os.write(qrCodeBytes);
//                os.flush();
//            }
//
//            ToolBean.info("永久二维码生成成功，场景值：[" + sceneStr + "]，文件名：[" + validFileName + "]，ticket：[" + ticket.getTicket() + "]");
//            return ResponseEntity.ok().build();
//
//        } catch (WxErrorException e) {
//            ToolBean.info("微信接口错误：" + e.getError().getErrorMsg() + "，错误码：" + e.getError().getErrorCode() + "，场景值：[" + sceneStr + "]");
//            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
//                    .body("生成二维码失败：" + e.getError().getErrorMsg());
//        } catch (Exception e) {
//            ToolBean.info("生成永久二维码发生未知错误:" + e.toString() + "，场景值：[" + sceneStr + "]，文件名：[" + fileName + "]");
//            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
//                    .body("生成二维码失败：系统错误");
//        }
//    }

    /**
     * 公共跳转界面
     * @return
     * @throws WxErrorException
     */
    @RequestMapping("/login")
    public ResultInfo login(@RequestBody ReqWxLogin reqWxLogin) throws WxErrorException {
        try {

            if (null==reqWxLogin){
                return new ResultInfo(500, "微信登录授权信息丢失！", null);
            }
            String code = reqWxLogin.getCode();
            String state = reqWxLogin.getState();

            if (StringUtils.isEmpty(code)){
                return new ResultInfo(500, "微信登录授权CODE丢失！", null);
            }

            RestTemplate restTemplate = new RestTemplate();
            // 1. 构造微信官方接口URL（获取access_token和openid）
            String url = String.format(
                    "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code",
                    wxMpService.getWxMpConfigStorage().getAppId(), wxMpService.getWxMpConfigStorage().getSecret(), code
            );

            String rtn;

            try{
                rtn = restTemplate.getForObject(url, String.class);
            }catch (HttpStatusCodeException e){
                rtn = e.getResponseBodyAsString();
                return new ResultInfo(500, "微信登录授权发生错误！["+rtn+"]", null);
            }

            // 2. 返回转换成JSON
            JSONObject result = JSONObject.parseObject(rtn);

            // 3. 解析返回结果（微信接口返回格式：{"access_token":"...","openid":"...",...}）
            if (result.containsKey("errcode")) {
                // 错误处理（如code无效）
                String errMsg = (String) result.get("errmsg");
                return new ResultInfo(500, "获取用户信息失败！["+errMsg+"]", null);
            }

            // 4. 提取openid（静默授权核心目标）
            String openid = (String) result.get("openid");
            ToolBean.info("用户openid：" + openid);

            if (StringUtils.isEmpty(openid)) {
                return new ResultInfo(500, "获取用户信息失败！", null);
            }

            THyxx tHyxx = new THyxx();
            tHyxx = tHyxxDao.getHyxxByOpenid(openid);

            if (tHyxx!=null){

                //如果用户没有秘钥，补充秘钥
                if (StringUtils.isEmpty(tHyxx.getAeskey()) || StringUtils.isEmpty(tHyxx.getAesiv())){
                    tHyxx.setAeskey(ToolBean.getRandomString(16));
                    tHyxx.setAesiv("0102030405060708");
                    tHyxxDao.updateById(tHyxx);
                }
                //校验完，准备登录
                StpUtil.login(tHyxx.getLsh());
                // 第2步，获取 Token  相关参数
                SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
                // 第3步，返回给前端
                String token = tokenInfo.getTokenValue();
                String data = "{\"code\":\"200\",\"token\":\"" + token + "\",\"a\":\"" + tHyxx.getAeskey() + "\",\"b\":\"" + tHyxx.getAesiv() + "\",\"c\":\"" + tHyxx.getLsh() + "\"}";
                ToolBean.info("登录成功，准备加密后返回的字符串:"+data);
                String rtnStr = Aes.encrypt(data,"NLfZ3aIOg77E2rT8");
                return new ResultInfo(200, "登录成功！",rtnStr);
            }else{
                tHyxx = new THyxx();
                tHyxx.setOpenid(openid);
                tHyxx.setAeskey(ToolBean.getRandomString(16));
                tHyxx.setAesiv("0102030405060708");
                tHyxxDao.insert(tHyxx);

                //校验完，准备登录
                StpUtil.login(tHyxx.getLsh());
                // 第2步，获取 Token  相关参数
                SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
                // 第3步，返回给前端
                String token = tokenInfo.getTokenValue();
                String data = "{\"code\":\"200\",\"token\":\"" + token + "\",\"a\":\"" + tHyxx.getAeskey() + "\",\"b\":\"" + tHyxx.getAesiv() + "\",\"c\":\"" + tHyxx.getLsh() + "\"}";
                ToolBean.info("登录成功，准备加密后返回的字符串:"+data);
                String rtnStr = Aes.encrypt(data,"NLfZ3aIOg77E2rT8");
                return new ResultInfo(200, "登录成功！",rtnStr);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return new ResultInfo(500, "获取用户信息失败！["+e.toString()+"]", null);
        }
    }

    @PostMapping("/login_sjh")
    public ResultInfo loginSjh(@RequestBody ReqLoginSjh reqLoginSjh){
        if (null==reqLoginSjh){
            return new ResultInfo(500, "缺少手机号，无法完成登录！",null);
        }
        try {
            THyxx tHyxx = new THyxx();
            tHyxx = tHyxxDao.getHyxxByOpenid(reqLoginSjh.getSjh());

            if (tHyxx!=null){
                //如果用户没有秘钥，补充秘钥
                if (StringUtils.isEmpty(tHyxx.getAeskey()) || StringUtils.isEmpty(tHyxx.getAesiv())){
                    tHyxx.setAeskey(ToolBean.getRandomString(16));
                    tHyxx.setAesiv("0102030405060708");
                    tHyxxDao.updateById(tHyxx);
                }
                //校验完，准备登录
                StpUtil.login(tHyxx.getLsh());
                // 第2步，获取 Token  相关参数
                SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
                // 第3步，返回给前端
                String token = tokenInfo.getTokenValue();
                String data = "{\"code\":\"200\",\"token\":\"" + token + "\",\"a\":\"" + tHyxx.getAeskey() + "\",\"b\":\"" + tHyxx.getAesiv() + "\",\"c\":\"" + tHyxx.getLsh() + "\"}";
                ToolBean.info("登录成功，准备加密后返回的字符串:"+data);
                String rtnStr = Aes.encrypt(data,"NLfZ3aIOg77E2rT8");
                return new ResultInfo(200, "登录成功！",rtnStr);
            }else{
                return new ResultInfo(500, "用户没有访问权限！请在后台维护用户信息！", null);
            }

        } catch (Exception e) {
            e.printStackTrace();
            return new ResultInfo(500, "登录失败：" + e.getMessage(),null);
        }
    }

    /**
     * 获取授权地址
     */
    @GetMapping("/buildOauth2Url")
    public ResultInfo oauth2Url(String redirect) throws UnsupportedEncodingException {

        String url = messageService.getOauthUrl(redirect);
        if (!StringUtils.isEmpty(url))
            return new ResultInfo(200, "获取授权地址成功！",url);
        else
            return new ResultInfo(500, "获取授权地址失败！",url);
    }

    /**
     * 处理微信消息
     */
    @RequestMapping("/wxmenu")
    public String handleMessage() {
        return "菜单生成结果："+wechatServices.createMenu();
    }
}
